/*
 * Created on 2005-3-4
 */
package com.hd123.rumba.request;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.ecs.ConcreteElement;
import org.apache.ecs.Element;
import org.apache.ecs.html.A;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.Label;
import org.apache.ecs.html.Option;
import org.apache.ecs.html.Select;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TR;
import org.apache.ecs.html.Table;
import org.apache.ecs.html.TextArea;

import com.hd123.rumba.runtime.Runtime;
import com.hd123.rumba.util.AccessMode;
import com.hd123.rumba.util.HashMap2;
import com.hd123.rumba.util.StringUtil;

/**
 * @author caili
 */
/**
 * @author caili
 */
public class JspLib {

  /**
   * 如果fieldName在dd.getInvalidFormValues()中存在, 则返回红色粗体的content;否则返回content.
   * 
   * @param content
   * @param fieldName
   * @param dd
   * @return
   */
  public static String emphasize(String content, String fieldName, Dictionary dd) {
    String s = content;
    if (dd != null) {
      if (dd.getInvalidFormValues().containsKey(fieldName))
        s = "<b><font color=red>" + content + "</font></b>";
    }
    return s;
  }

  public static Object getFormValue(String key, Dictionary dd) {
    if (dd != null) {
      return dd.getFormValues().get(key);
    }
    return null;
  }

  public static Object putFormValue(String key, Object value, Dictionary dd) {
    if (dd != null) {
      return dd.getFormValues().put(key, value);
    }
    return null;
  }

  public static Object getValue(String key, Dictionary dd) {
    if (dd != null) {
      return dd.get(key);
    }
    return null;
  }

  public static Object putValue(String key, Object value, Dictionary dd) {
    if (dd != null) {
      return dd.put(key, value);
    }
    return null;
  }

  public static Object getSessionValue(String key, Dictionary dd) {
    if (dd != null) {
      return dd.getSessionValues().get(key);
    }
    return null;
  }

  public static Object putSessionValue(String key, Object value, Dictionary dd) {
    if (dd != null) {
      return dd.getSessionValues().put(key, value);
    }
    return null;
  }

  public static boolean isDefined(String key, Dictionary dd) {
    return dd != null
        && (dd.containsKey(key) || dd.getFormValues().containsKey(key) || dd.getSessionValues()
            .containsKey(key));
  }

  public static String getAction(String relativeUrl) {
    return Runtime.getAction(relativeUrl);
  }

  public static String getAction(Dictionary dd, String relativeUrl) {
    if (ExternalSession.isExternalSession(dd.getSession()))
      return Runtime.getExternalAction(relativeUrl);
    else
      return Runtime.getAction(relativeUrl);
  }

  private static Hashtable templateMap = new Hashtable();

  public static void clearTemplateMap() {
    templateMap.clear();
  }

  public static String getTemplate(String relativeUrl) {
    String jspUri = (String) templateMap.get(relativeUrl);
    if (jspUri == null || "true".equals(ActionConstants.RESEARCHTEMPLATE)) {
      jspUri = Runtime.getTemplate(relativeUrl);
      templateMap.put(relativeUrl, jspUri);
    }
    return jspUri;
  }

  public static String getStaticContent(String relativeUrl) {
    return ActionConstants.STATICCONTENTURL + StringUtil.encodeFileName(relativeUrl);
  }

  public static String getDocContent(String relativeUrl) {
    return ActionConstants.DOCCONTENTURL + StringUtil.encodeFileName(relativeUrl);
  }

  public static String getFormattedValue(String key, String pattern, Dictionary dd) {
    String s = "";
    if (dd != null) {
      if (dd.containsKey(key))
        s = format(dd.get(key), pattern);
    }
    return s;
  }

  public static String format(Date date, SimpleDateFormat sdf) {
    if (date == null)
      return "";
    return sdf.format(date);
  }

  /**
   * 以pattern格式返回obj的字符串表示.
   * 
   * @param obj
   * @param pattern
   * @return
   */
  public static String format(Object obj, String pattern) {
    String s = null;
    if (obj == null) {
      s = "";
    } else if (obj instanceof Date) {
      if (pattern == null || pattern.trim().length() == 0)
        pattern = "yyyy-MM-dd HH:mm:ss";
      SimpleDateFormat sdf = new SimpleDateFormat(pattern);
      s = sdf.format(obj);
    } else if (obj instanceof BigDecimal) {
      if (pattern == null || pattern.trim().length() == 0)
        s = obj.toString();
      else {
        DecimalFormat df = new DecimalFormat(pattern);
        s = df.format(obj);
      }
    } else if (obj instanceof BigInteger) {
      pattern = "0.00";
      DecimalFormat df = new DecimalFormat(pattern);
      s = df.format(obj);
    } else if ((obj instanceof Byte) || (obj instanceof Short) || (obj instanceof Integer)
        || (obj instanceof Long) || (obj instanceof BigInteger)) {
      if (pattern == null || pattern.trim().length() == 0)
        pattern = "0";
      DecimalFormat df = new DecimalFormat(pattern);
      s = df.format(obj);
    } else if (obj instanceof Boolean) {
      s = ((Boolean) obj).booleanValue() ? "是" : "否";
    } else {
      s = obj.toString();
    }
    return StringUtil.stringToHtml(s);
  }

  public static String format(Object obj) {
    return format(obj, null);
  }

  /**
   * 替换回车键为&lt;br&gt;
   * 
   * @param s
   * @return
   */
  public static String formatToHtml(String s) {
    if (s == null)
      return "";
    return StringUtil.stringToHtml(s).replaceAll("[\\r|\\n]", "<br>");
  }

  public static String formatToJS(String s) {
    if (s == null)
      return "";
    else
      return StringUtil.stringToJS(s);
  }

  public static String format(boolean b) {
    return b ? "是" : "否";
  }

  public static String navtree(Dictionary dd) {
    StringBuffer sb = new StringBuffer();
    String s = null;
    sb.append("var TREE_ITEMS = [");
    sb.append("['数据字典', null,\n");
    sb.append("['字典内容', null,\n");
    s = navtree(dd.getSessionValues());
    if (s == null) {
      sb.append("['sessionValues', null],\n");
    } else {
      sb.append("['sessionValues', null, \n");
      sb.append(s);
      sb.append("],\n");
    }
    s = navtree(dd.getFormValues());
    if (s == null) {
      sb.append("['formValues', null],\n");
    } else {
      sb.append("['formValues', null, \n");
      sb.append(s);
      sb.append("],\n");
    }
    s = navtree((Hashtable) dd);
    if (s == null) {
      sb.append("['dictionaryValues', null]\n");
    } else {
      sb.append("['dictionaryValues', null, \n");
      sb.append(s);
      sb.append("]");
    }
    sb.append("]]]");
    return sb.toString();
  }

  public static String navtree(Hashtable h) {
    StringBuffer sb = new StringBuffer();
    Enumeration e = h.keys();
    while (e.hasMoreElements()) {
      String key = (String) e.nextElement();
      Object obj = h.get(key);
      String value = obj.toString() + "(" + obj.getClass().getName() + ")";
      sb.append("['" + key + "=" + value + "', null]\n");
      if (e.hasMoreElements())
        sb.append(",");
    }
    if (sb.length() == 0)
      return null;
    return sb.toString();
  }

  public static String getTempImportDir(HttpServletRequest request) {
    return request.getSession().getServletContext().getRealPath(ActionConstants.TEMPIMPORTDIR);
  }

  public static String getTempExportDir(HttpServletRequest request) {
    return request.getSession().getServletContext().getRealPath(ActionConstants.TEMPEXPORTDIR);
  }

  public static int getAccessMode(Dictionary dd, String permissionId, String formState,
      String valueShowEdit, boolean alwaysWritable) {
    if (formState == null)
      formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    if (formState == null)
      formState = JspLib.VALUE_FORMSTATE_VIEW;

    int mode = AccessMode.READWRITE;
    if (alwaysWritable) {
      mode = AccessMode.READWRITE;
    } else {
      if (permissionId == null) {
        mode = AccessMode.READWRITE;
      } else {
        mode = AccessMode.INVISIBLE;
        AccessMode am = (AccessMode) dd.get("am");
        if (am != null) {
          mode = am.getAccessMode(permissionId);
          if (mode == -1)
            mode = AccessMode.INVISIBLE;
        }
      }
      if (JspLib.VALUE_FORMSTATE_EDIT.equals(formState) && "true".equals(valueShowEdit)
          || JspLib.VALUE_FORMSTATE_CREATE.equals(formState))
        mode = Math.min(mode, AccessMode.READWRITE);
      else
        mode = Math.min(mode, AccessMode.READONLY);
    }
    return mode;
  }

  public static String createEditFieldHtml(Dictionary dd, Object[] params) {
    String name = null; // required
    String labelName = null; // 标题:代码 名称 中的名称. 如果有定义, 在VIEW的时候, 会显示为[名称值]
    String valueComponent = null; // 比如在输入框边的一个按钮. VIEW的时候不显示
    String isRequired = "false"; // true时在标题边显示红色的*
    String canEdit = "true"; // canEdit=false时不论formState总是不可编辑的.
    boolean valueComponentAlwaysShow = false;
    boolean showCalendar = false;
    boolean selectProduct = false;
    boolean selectConsumer = false;
    boolean selectBrand = false;
    boolean selectMunit = false;
    boolean selectItemNameTab = false;
    boolean selectProductCategory = false;
    boolean selectProductTypeGroup = false;
    boolean selectSupplier = false;
    boolean selectBusinessWrh = false;
    boolean selectOrganization = false;
    boolean selectPriceGroup = false;
    boolean selectUser = false;
    boolean selectServicePerson = false;
    boolean selectEmployee = false;
    boolean selectVehicle = false;
    String productSupplierUuid = "";
    String codeName = "false";
    String organization = null;
    String isStore = "false";
    String isBuyer = "false";
    String isTransfer = "false";
    String selectProductCallback = null;
    String selectConsumerCallback = null;
    String selectBrandCallback = null;
    String selectMunitCallback = null;
    String selectItemNameTabCallback = null;
    String classNo = ""; // 费用类型代码中的财务代码
    String selectProductCategoryCallback = null;
    String selectProductTypeGroupCallback = null;
    String selectSupplierCallback = null;
    String selectBusinessWrhCallback = null;
    String selectOrganizationCallback = null;
    String selectPriceGroupCallback = null;
    String selectUserCallback = null;
    String selectServicePersonCallback = null;
    String selectEmployeeCallback = null;
    String selectVehicleCallback = null;

    // 标题属性
    String caption = null; // required
    Hashtable captionAttr = new Hashtable(); // 附加的标题<td>属性
    String captionClassError = "fielditem2_error";
    String captionClassNormal = "infobox_title";
    String captionErrorDisplay = "false";
    // dd.getFormInvalidValues().containsKey(name_invalid/missing/error)时是否要以错误方式显示

    // 值属性
    String value = null; // 如果没有指定, 取dd.getFormValue(name);
    String valueClass = "infobox_item";
    Hashtable valueAttr = new Hashtable();
    String valueInputType = "input";
    String valueInputClass = "inputfield_en";
    Hashtable valueInputAttr = new Hashtable();
    String labelValue = null; // 如果没有指定, 取dd.getFormValue(labelName);
    String valueFormat = null;

    // 以下4个参数决定了显示模式: 不可见, 只读和读写
    String permissionId = null; // 如果指定了,
    // 查user是否具有permissionId.readonly或permissionId.readwrite权限
    String formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    String valueShowEdit = "true"; // formState=="edit"时是否可编辑. id字段是不能编辑的.
    boolean alwaysWritable = false; // 是否总是可编辑的. 查询条件总是可编辑的.

    // User user = dd.getCurrentUser();

    // set variables
    for (int i = 0; i < params.length; ++i) {
      String paramName = (String) params[i];
      Object paramValue = params[i + 1];
      if (paramName.equalsIgnoreCase("name"))
        name = (String) paramValue;
      else if (paramName.equalsIgnoreCase("caption"))
        caption = (String) paramValue;
      else if (paramName.equalsIgnoreCase("captionAttr")) {
        captionAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase("captionClassError"))
        captionClassError = (String) paramValue;
      else if (paramName.equalsIgnoreCase("captionClassNormal"))
        captionClassNormal = (String) paramValue;
      else if (paramName.equalsIgnoreCase("captionErrorDisplay"))
        captionErrorDisplay = (String) paramValue;
      else if (paramName.equalsIgnoreCase("canEdit"))
        canEdit = (String) paramValue;
      else if (paramName.equalsIgnoreCase("value"))
        value = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueClass"))
        valueClass = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueAttr")) {
        valueAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase("valueInputType"))
        valueInputType = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueInputClass"))
        valueInputClass = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueInputAttr")) {
        valueInputAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase("permissionId"))
        permissionId = (String) paramValue;
      else if (paramName.equalsIgnoreCase(JspLib.ID_FORMSTATE))
        formState = (String) paramValue;
      // else if (paramName.equalsIgnoreCase("user"))
      // user = (User) paramValue;
      else if (paramName.equalsIgnoreCase("valueShowEdit"))
        valueShowEdit = (String) paramValue;
      else if (paramName.equalsIgnoreCase("alwaysWritable"))
        alwaysWritable = "true".equalsIgnoreCase((String) paramValue);
      else if (paramName.equals("labelName"))
        labelName = (String) paramValue;
      else if (paramName.equals("valueComponent"))
        valueComponent = (String) paramValue;
      else if (paramName.equals("isRequired"))
        isRequired = (String) paramValue;
      else if (paramName.equals("valueFormat"))
        valueFormat = (String) paramValue;
      else if (paramName.equals("valueComponentAlwaysShow"))
        valueComponentAlwaysShow = "true".equalsIgnoreCase((String) paramValue);
      else if (paramName.equals("showCalendar"))
        showCalendar = "true".equalsIgnoreCase((String) paramValue);
      else if (paramName.equals("selectProduct")) {
        productSupplierUuid = (String) paramValue;
        selectProduct = true;
      } else if (paramName.equals("selectProductCallback")) {
        selectProductCallback = (String) paramValue;
      } else if (paramName.equals("selectConsumer")) {
        selectConsumer = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectConsumerCallback")) {
        selectConsumerCallback = (String) paramValue;
      } else if (paramName.equals("selectBrand")) {
        selectBrand = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectBrandCallback")) {
        selectBrandCallback = (String) paramValue;
      } else if (paramName.equals("selectMunit")) {
        selectMunit = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectMunitCallback")) {
        selectMunitCallback = (String) paramValue;
      } else if (paramName.equals("selectItemNameTab")) {
        classNo = (String) paramValue;
        selectItemNameTab = true;
      } else if (paramName.equals("selectItemNameTabCallback")) {
        selectItemNameTabCallback = (String) paramValue;
      } else if (paramName.equals("selectProductCategory")) {
        selectProductCategory = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectProductCategoryCallback")) {
        selectProductCategoryCallback = (String) paramValue;
      } else if (paramName.equals("selectProductTypeGroup")) {
        selectProductTypeGroup = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectProductTypeGroupCallback")) {
        selectProductTypeGroupCallback = (String) paramValue;
      } else if (paramName.equals("selectSupplier")) {
        selectSupplier = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectSupplierCallback")) {
        selectSupplierCallback = (String) paramValue;
      } else if (paramName.equals("selectBusinessWrh")) {
        selectBusinessWrh = true;
        codeName = (String) params[i + 1];
        organization = (String) params[i + 2];
        ++i;
      } else if (paramName.equals("selectBusinessWrhCallback")) {
        selectBusinessWrhCallback = (String) paramValue;
      } else if (paramName.equals("selectOrganization")) {
        selectOrganization = true;
        codeName = (String) params[i + 1];
        isStore = (String) params[i + 2];
        isTransfer = (String) params[i + 3];
        ++i;
        ++i;
      } else if (paramName.equals("selectOrganizationCallback")) {
        selectOrganizationCallback = (String) paramValue;
      } else if (paramName.equals("selectPriceGroup")) {
        selectPriceGroup = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectPriceGroupCallback")) {
        selectPriceGroupCallback = (String) paramValue;
      } else if (paramName.equals("selectUser")) {
        selectUser = true;
        codeName = (String) params[i + 1];
        isBuyer = (String) params[i + 2];
        ++i;
      } else if (paramName.equals("selectUserCallback")) {
        selectUserCallback = (String) paramValue;
      } else if (paramName.equals("selectServicePerson")) {
        selectServicePerson = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectServicePersonCallback")) {
        selectServicePersonCallback = (String) paramValue;
      } else if (paramName.equals("selectEmployee")) {
        selectEmployee = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectEmployeeCallback")) {
        selectEmployeeCallback = (String) paramValue;
      } else if (paramName.equals("selectVehicle")) {
        selectVehicle = true;
        codeName = (String) paramValue;
      } else if (paramName.equals("selectVechileCallback")) {
        selectVehicleCallback = (String) paramValue;
      }
      ++i;
    }
    if (value == null) {
      if (dd.getFormValue(name) instanceof String)
        value = (String) dd.getFormValue(name);
      else
        value = format(dd.getFormValue(name), valueFormat);
    }
    if (value == null) {
      value = "";
    }
    if ("checkbox".equalsIgnoreCase(valueInputType)) {
      value = dd.getFormValues().containsKey(name) ? "是" : "否";
    }
    if (labelValue == null && labelName != null)
      labelValue = (String) dd.getFormValue(labelName);

    int mode = getAccessMode(dd, permissionId, formState, valueShowEdit, alwaysWritable);
    if ("false".equals(canEdit) && mode == AccessMode.READWRITE)
      mode = AccessMode.READONLY;

    // label
    TD tdLabel = new TD();
    tdLabel.setNoWrap(true);
    tdLabel.setAlign("right");
    if ("textarea".equals(valueInputType))
      tdLabel.setVAlign("top");
    if (captionErrorDisplay.equalsIgnoreCase("true")) {
      if (dd.getInvalidFormValues().containsKey(name + "_missing")
          || dd.getInvalidFormValues().containsKey(name + "_invalid")
          || dd.getInvalidFormValues().containsKey(name + "_error"))
        tdLabel.setClass(captionClassError);
      else
        tdLabel.setClass(captionClassNormal);
    } else
      tdLabel.setClass(captionClassNormal);
    setAttributes(tdLabel, captionAttr);
    Label label = new Label();
    label.setFor(name);
    if ("true".equals(isRequired) && mode == AccessMode.READWRITE)
      label.addElement(caption + "<font color=red>*</font>:");
    else
      label.addElement(caption + ":");
    tdLabel.addElement(label);

    // content
    TD content = new TD();
    content.setClass(valueClass);
    setAttributes(content, valueAttr);
    if (mode == AccessMode.INVISIBLE)
      content.addElement("******");
    else if (mode == AccessMode.READONLY) {
      content.addElement("textarea".equals(valueInputType) ? formatToHtml(value)
          : (value == "" ? "&nbsp;" : value));
      if (labelValue != null && labelValue.trim().length() != 0)
        content.addElement("[" + labelValue + "]");
      if ("false".equalsIgnoreCase(valueShowEdit)) {
        Input input = new Input();
        input.setID(name);
        input.setName(name);
        input.setType("hidden");
        if (valueInputType.equalsIgnoreCase("input")) {
          input.setValue(format(value, valueFormat));
        } else if (valueInputType.equalsIgnoreCase("checkbox")) {
          input.setChecked(dd.getFormValues().containsKey(name));
        }
        content.addElement(input);
      }
      if (valueComponent != null && valueComponentAlwaysShow)
        content.addElement(valueComponent);
    } else {
      Element editor = null;
      if ("textarea".equals(valueInputType)) {
        TextArea input = new TextArea();
        input.setName(name);
        input.setClass(valueInputClass);
        setAttributes(input, valueInputAttr);
        input.addElement(value);
        editor = input;
      } else {
        Input input = new Input();
        input.setName(name);
        input.setType(valueInputType);
        input.setClass(valueInputClass);
        input.setID(name);
        setAttributes(input, valueInputAttr);
        if (valueInputType.equalsIgnoreCase("input")) {
          input.setValue(value);
        } else if (valueInputType.equalsIgnoreCase("checkbox")) {
          input.setType("checkbox");
          input.setChecked(dd.getFormValues().containsKey(name));
        }
        editor = input;
      }
      content.addElement(editor);
      if (labelValue != null)
        content.addElement(labelValue);
      if (showCalendar) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:showCalendar('" + name + "_calimage',false,'" + name
            + "',null);\">" + "<img id='" + name + "_calimage' width=18 height=18 src='"
            + getStaticContent("rumba/js/calendar/button.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectProduct) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectProduct('" + name + "_psimage','" + name + "','"
            + productSupplierUuid + "'"
            + (selectProductCallback == null ? "" : (",'" + selectProductCallback) + "'") + ");\">"
            + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectConsumer) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectConsumer('" + name + "_psimage','" + name + "','"
            + codeName + "'"
            + (selectConsumerCallback == null ? "" : (",'" + selectConsumerCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectBrand) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectBrand('" + name + "_psimage','" + name + "','" + codeName
            + "'" + (selectBrandCallback == null ? "" : (",'" + selectBrandCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectMunit) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectMunit('" + name + "_psimage','" + name + "','" + codeName
            + "'" + (selectMunitCallback == null ? "" : (",'" + selectMunitCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectItemNameTab) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectItemNameTab('" + name + "_psimage','" + name + "','"
            + classNo + "'"
            + (selectItemNameTabCallback == null ? "" : (",'" + selectItemNameTabCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectProductCategory) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectProductCategory('"
            + name
            + "_psimage','"
            + name
            + "','"
            + codeName
            + "'"
            + (selectProductCategoryCallback == null ? "" : (",'" + selectProductCategoryCallback)
                + "'") + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectProductTypeGroup) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectProductTypeGroup('"
            + name
            + "_psimage','"
            + name
            + "','"
            + codeName
            + "'"
            + (selectProductTypeGroupCallback == null ? ""
                : (",'" + selectProductTypeGroupCallback) + "'") + ");\">" + "<img id='" + name
            + "_psimage' width=18 height=18 src='" + getStaticContent("rumba/images/search.gif")
            + "' border=0 align=top>" + "</a>");
      }
      if (selectSupplier) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectSupplier('" + name + "_psimage','" + name + "','"
            + codeName + "'"
            + (selectSupplierCallback == null ? "" : (",'" + selectSupplierCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectBusinessWrh) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectBusinessWrh('" + name + "_psimage','" + name + "','"
            + codeName + "', '" + organization + "'"
            + (selectBusinessWrhCallback == null ? "" : (",'" + selectBusinessWrhCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectOrganization) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectOrganization('" + name + "_psimage','" + name + "','"
            + codeName + "','" + isStore + "', '" + isTransfer + "'"
            + (selectOrganizationCallback == null ? "" : (",'" + selectOrganizationCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectPriceGroup) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectPriceGroup('" + name + "_psimage','" + name + "','"
            + codeName + "'"
            + (selectPriceGroupCallback == null ? "" : (",'" + selectPriceGroupCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectUser) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectUser('" + name + "_psimage','" + name + "','" + codeName
            + "','" + isBuyer + "'"
            + (selectUserCallback == null ? "" : (",'" + selectUserCallback) + "'") + ");\">"
            + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectServicePerson) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectServicePerson('"
            + name
            + "_psimage','"
            + name
            + "','"
            + codeName
            + "','"
            + isBuyer
            + "'"
            + (selectServicePersonCallback == null ? "" : (",'" + selectServicePersonCallback)
                + "'") + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectEmployee) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectEmployee('" + name + "_psimage','" + name + "','"
            + codeName + "'"
            + (selectEmployeeCallback == null ? "" : (",'" + selectEmployeeCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (selectVehicle) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:selectVehicle('" + name + "_psimage','" + name + "','" + codeName
            + "'" + (selectVehicleCallback == null ? "" : (",'" + selectVehicleCallback) + "'")
            + ");\">" + "<img id='" + name + "_psimage' width=18 height=18 src='"
            + getStaticContent("rumba/images/search.gif") + "' border=0 align=top>" + "</a>");
      }
      if (valueComponent != null)
        content.addElement(valueComponent);
    }
    return tdLabel.toString() + content.toString();
  }

  public static void setAttributes(ConcreteElement e, Hashtable attrs) {
    Enumeration keys = attrs.keys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      e.addAttribute(key, attrs.get(key));
    }
  }

  public static String createEditCellHtml(Dictionary dd, Object[] params) {
    String name = null; // required
    String canEdit = "true"; // canEdit=false时不论formState总是不可编辑的.
    String valueComponent = null; // 比如在输入框边的一个按钮. VIEW的时候不显示
    String valueFormat = null;

    // 值属性
    String valueClassError = "fielditem2_error e s";
    String valueClassNormal = "e s";
    String valueErrorDisplay = "false";
    // dd.getFormInvalidValues().containsKey(name_invalid/missing/error)时是否要以错误方式显示
    String value = null; // 如果没有指定, 取dd.getFormValue(name);
    Hashtable valueAttr = new Hashtable();
    String valueInputType = "input";
    String valueInputClass = "inputfield_en";
    boolean showCalendar = false;
    Hashtable valueInputAttr = new Hashtable();

    // 以下4个参数决定了显示模式: 不可见, 只读和读写
    String permissionId = null; // 如果指定了,
    // 查user是否具有permissionId.readonly或permissionId.readwrite权限
    String formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    String valueShowEdit = "true"; // formState=="edit"时是否可编辑. id字段是不能编辑的.
    boolean alwaysWritable = false; // 是否总是可编辑的. 查询条件总是可编辑的.

    // set variables
    for (int i = 0; i < params.length; ++i) {
      String paramName = (String) params[i];
      Object paramValue = params[i + 1];
      if (paramName.equalsIgnoreCase("name")) {
        name = (String) paramValue;
      } else if (paramName.equalsIgnoreCase("canEdit"))
        canEdit = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueClassError"))
        valueClassError = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueClassNormal"))
        valueClassNormal = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueErrorDisplay"))
        valueErrorDisplay = (String) paramValue;
      else if (paramName.equalsIgnoreCase("value"))
        value = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueAttr")) {
        valueAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase("valueInputType"))
        valueInputType = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueInputClass"))
        valueInputClass = (String) paramValue;
      else if (paramName.equalsIgnoreCase("valueInputAttr")) {
        valueInputAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase("permissionId"))
        permissionId = (String) paramValue;
      else if (paramName.equalsIgnoreCase(JspLib.ID_FORMSTATE))
        formState = (String) paramValue;
      // else if (paramName.equalsIgnoreCase("user"))
      // user = (User) paramValue;
      else if (paramName.equalsIgnoreCase("valueShowEdit"))
        valueShowEdit = (String) paramValue;
      else if (paramName.equalsIgnoreCase("alwaysWritable"))
        alwaysWritable = "true".equalsIgnoreCase((String) paramValue);
      else if (paramName.equals("valueComponent"))
        valueComponent = (String) paramValue;
      else if (paramName.equals("valueFormat"))
        valueFormat = (String) paramValue;
      else if (paramName.equals("showCalendar"))
        showCalendar = "true".equalsIgnoreCase((String) paramValue);
      ++i;
    }
    if (value == null)
      value = format(dd.getFormValue(name), valueFormat);
    if (value == null)
      value = "";
    if ("checkbox".equalsIgnoreCase(valueInputType))
      value = dd.getFormValues().containsKey(name) ? "是" : "否";

    int mode = getAccessMode(dd, permissionId, formState, valueShowEdit, alwaysWritable);
    if ("false".equals(canEdit) && mode == AccessMode.READWRITE)
      mode = AccessMode.READONLY;

    // cell content
    TD content = new TD();

    if (valueErrorDisplay.equalsIgnoreCase("true")) {
      if (dd.getInvalidFormValues().containsKey(name + JspLib.POSTFIX_FIELD_MISSING)
          || dd.getInvalidFormValues().containsKey(name + JspLib.POSTFIX_FIELD_INVALID)
          || dd.getInvalidFormValues().containsKey(name + JspLib.POSTFIX_FIELD_ERROR))
        content.setClass(valueClassError);
      else
        content.setClass(valueClassNormal);
    } else
      content.setClass(valueClassNormal);
    setAttributes(content, valueAttr);
    if (mode == AccessMode.INVISIBLE)
      content.addElement("******");
    else if (mode == AccessMode.READONLY) {
      content.addElement("textarea".equals(valueInputType) ? formatToHtml(value)
          : (value == "" ? "&nbsp;" : value));
      if ("false".equalsIgnoreCase(valueShowEdit)) {
        Input input = new Input();
        input.setName(name);
        input.setType("hidden");
        if (valueInputType.equalsIgnoreCase("input")) {
          input.setValue(format(value, valueFormat));
        } else if (valueInputType.equalsIgnoreCase("checkbox")) {
          input.setChecked(dd.getFormValues().containsKey(name));
        }
        content.addElement(input);
      }
      content.addElement("&nbsp;");
    } else {
      Element editor = null;
      if ("textarea".equals(valueInputType)) {
        TextArea input = new TextArea();
        input.setName(name);
        input.setClass(valueInputClass);
        setAttributes(input, valueInputAttr);
        input.addElement(value);
        editor = input;
      } else {
        Input input = new Input();
        input.setName(name);
        input.setType(valueInputType);
        input.setClass(valueInputClass);
        setAttributes(input, valueInputAttr);
        if (valueInputType.equalsIgnoreCase("input")) {
          input.setValue(value);
        } else if (valueInputType.equalsIgnoreCase("checkbox")) {
          input.setType("checkbox");
          input.setChecked(dd.getFormValues().containsKey(name));
        }
        editor = input;
      }
      content.addElement(editor);
      if (showCalendar) {
        content.addElement("<a onclick='event.cancelBubble=true;' "
            + " href=\"javascript:showCalendar('" + name + "_calimage',false,'" + name
            + "',null);\">" + "<img id='" + name + "_calimage' width=18 height=18 src='"
            + getStaticContent("rumba/js/calendar/button.gif") + "' border=0 align=top>" + "</a>");
      }
      if (valueComponent != null)
        content.addElement(valueComponent);
    }
    return content.toString();
  }

  /**
   * 构造的HTML中不包括&lt;td&gt; <br>
   * 使用时, 当前选中的项的option value值等于dd.getFormValue(name) <br>
   * 特别地, 当设置为只读的时候, 如果找到选中的项, 显示option的名字; 否则显示dd.getFormValue(name). <br>
   * 参数中可包含1个hidden value和hidden label. 这个值不被作为下拉列表的候选值. 当参数中只有这个值的时候,
   * 生成一个hidden的input.
   * 
   * @param dd
   * @param params
   * @return
   * @throws Exception
   */
  public static String createSelectHtml(Dictionary dd, Object[] params) throws Exception {
    String name = null;
    String value;
    String label;
    String selectedValue = "";
    String valueComponent = null;
    String displayValueName = null; // 当view的时候,
    // dd.getFormValue(name)匹配不到option的value值时,
    // 显示dd.getFormValue(displayValueName)

    String permissionId = null;
    String formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    String valueShowEdit = "true";
    boolean alwaysWritable = false;

    Hashtable valueInputAttr = new Hashtable();

    Select select = new Select();
    Option option = null;
    int optionCount = 0;
    Input hiddenInput = null;
    // set variables
    for (int i = 0; i < params.length; ++i) {
      String paramName = (String) params[i];
      if (paramName.equalsIgnoreCase("name")) {
        name = (String) params[i + 1];
        select.setName(name);
      } else if (paramName.equalsIgnoreCase("option")) {
        value = (String) params[i + 1];
        label = (String) params[i + 2];
        ++i;
        option = new Option();
        option.setValue(value);
        option.addElement(label);
        if (value.equals(dd.getFormValue(name))) {
          option.setSelected(true);
          selectedValue = label;
        }
        select.addElement(option);
        ++optionCount;
      } else if (paramName.equalsIgnoreCase("hidden")) {
        value = (String) params[i + 1];
        label = (String) params[i + 2];
        ++i;
        hiddenInput = new Input();
        hiddenInput.setType("hidden");
        hiddenInput.setName(name);
        hiddenInput.setValue(value);
      } else if (paramName.equalsIgnoreCase("valueInputAttr")) {
        valueInputAttr.put(params[i + 1], params[i + 2]);
        ++i;
      } else if (paramName.equalsIgnoreCase(JspLib.ID_FORMSTATE)) {
        formState = (String) params[i + 1];
      } else if (paramName.equalsIgnoreCase("permissionId")) {
        permissionId = (String) params[i + 1];
      } else if (paramName.equalsIgnoreCase("alwaysWritable")) {
        alwaysWritable = "true".equalsIgnoreCase((String) (String) params[i + 1]);
      } else if (paramName.equalsIgnoreCase("valueComponent")) {
        valueComponent = (String) params[i + 1];
      } else if (paramName.equalsIgnoreCase("displayValueName")) {
        displayValueName = (String) params[i + 1];
      } else if (paramName.equalsIgnoreCase("valueShowEdit"))
        valueShowEdit = (String) params[i + 1];
      ++i;
    }

    if ("".equals(selectedValue) && displayValueName != null)
      selectedValue = (String) dd.getFormValue(displayValueName);
    if (selectedValue == null)
      selectedValue = "";

    int mode = getAccessMode(dd, permissionId, formState, valueShowEdit, alwaysWritable);
    if (mode == AccessMode.READWRITE) {
      if (optionCount > 0) {
        setAttributes(select, valueInputAttr);
        return select.toString() + (valueComponent == null ? "" : valueComponent);
      } else {
        return selectedValue + "&nbsp" + (hiddenInput == null ? "" : hiddenInput.toString());
      }
    } else if (mode == AccessMode.READONLY)
      return selectedValue + "&nbsp";
    else
      return "******";
  }

  /**
   * 将输入的params1和params2拼起来后调用createSelectHtml(Dictionary, Object[])
   * 
   * @param dd
   * @param params1
   * @param params2
   * @return
   * @throws Exception
   */
  public static String createSelectHtml(Dictionary dd, Object[] params1, Object[] params2)
      throws Exception {
    int len1 = params1 == null ? 0 : params1.length;
    int len2 = params2 == null ? 0 : params2.length;
    Object[] params = new Object[len1 + len2];
    for (int i = 0; i < len1; ++i)
      params[i] = params1[i];
    for (int i = 0; i < len2; ++i)
      params[i + len1] = params2[i];
    return createSelectHtml(dd, params);
  }

  public static String createRadioHtml(Dictionary dd, Object[] params) throws Exception {
    String name = null, value, label, selectedValue = "";

    String permissionId = null;
    String formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    String valueShowEdit = "true";
    List optionList = new ArrayList();
    Hashtable optionTdAttr = new Hashtable();
    // 是否使用td来分隔每个option。
    String optionWithTd = "false";
    // String optio
    boolean alwaysWritable = false;

    StringBuffer sb = new StringBuffer();
    Input option = null;
    // set variables
    for (int i = 0; i < params.length; ++i) {
      String paramName = (String) params[i];
      if (paramName.equalsIgnoreCase("name")) {
        name = (String) params[i + 1];
        i++;
      } else if (paramName.equalsIgnoreCase("optionWithTd")) {
        optionWithTd = (String) params[i + 1];
      } else if (paramName.equalsIgnoreCase("option")) {
        optionList.add(params[i + 1]);
        optionList.add(params[i + 2]);
        i += 2;
      } else if (paramName.equalsIgnoreCase("optionTdAttr")) {
        optionTdAttr.put(params[i + 1], params[i + 2]);
        i += 2;
      } else if (paramName.equalsIgnoreCase("permissionId")) {
        permissionId = (String) params[i + 1];
        i++;
      } else if (paramName.equalsIgnoreCase(JspLib.ID_FORMSTATE)) {
        formState = (String) params[i + 1];
        i++;
      } else if (paramName.equalsIgnoreCase("alwaysWritable")) {
        alwaysWritable = "true".equalsIgnoreCase((String) (String) params[i + 1]);
        i++;
      }
    }

    for (int i = 0; i < optionList.size(); i += 2) {
      value = (String) optionList.get(i);
      label = (String) optionList.get(i + 1);
      option = new Input();
      option.setType("radio");
      option.setName(name);
      option.setValue(value);
      option.addElement(label);
      if (value.equals(dd.getFormValue(name))) {
        option.setChecked(true);
        selectedValue = label;
      }
      if ("TRUE".equalsIgnoreCase(optionWithTd)) {
        TD td = new TD();
        setAttributes(td, optionTdAttr);
        td.addElement(option.toString());
        sb.append(td.toString());
      } else
        sb.append(option.toString());
    }

    int mode = getAccessMode(dd, permissionId, formState, valueShowEdit, alwaysWritable);
    if (mode == AccessMode.READWRITE)
      return sb.toString();
    else if (mode == AccessMode.READONLY) {
      if ("TRUE".equalsIgnoreCase(optionWithTd)) {
        TD td = new TD();
        optionTdAttr.put("colspan", String.valueOf(optionList.size() / 2));
        setAttributes(td, optionTdAttr);
        td.addElement(selectedValue);
        return td.toString();
      } else
        return selectedValue;
    } else
      return "******";
  }

  /**
   * @param dd
   * @param params
   *          每4个参数为一组, 依此为label, action, enabled, showWhenCreating
   * @return
   * @throws Exception
   */
  public static String createTabHtml(Dictionary dd, Object[] params) throws Exception {
    String label, action, enabled, showWhenCreating, formState;
    Boolean hasPermission;
    formState = (String) dd.getFormValue(JspLib.ID_FORMSTATE);
    if (formState == null)
      formState = JspLib.VALUE_FORMSTATE_VIEW;
    Table table = new Table();
    table.setBorder(0);
    table.setCellSpacing(0);
    table.setCellPadding(0);
    TR tr = new TR();
    table.addElement(tr);
    for (int i = 0; i < params.length;) {
      label = (String) params[i++];
      action = (String) params[i++];
      enabled = (String) params[i++];
      showWhenCreating = (String) params[i++];
      hasPermission = (Boolean) params[i++];
      if (hasPermission == null)
        hasPermission = Boolean.TRUE;
      if (hasPermission.booleanValue()
          && (!JspLib.VALUE_FORMSTATE_CREATE.equals(formState) || "true".equals(showWhenCreating))) {
        TD td = new TD();
        tr.addElement(td);
        td.setNoWrap(true);
        if ("enabled".equals(enabled)) {
          td.setClass("e table_tabs_en_background");
          td.addElement(label);
        } else {
          if (i < params.length)
            td.setClass("e table_tabs_dis_background");
          else
            td.setClass("table_tabs_dis_background");
          A a = new A();
          td.addElement(a);
          a.setClass("table_tabs_dis");
          a.setHref(JspLib.getAction(action));
          a.addElement(label);
        }
      }
    }
    return table.toString();
  }

  public static final String ID_FORMSTATE = "formState";
  public static final String VALUE_FORMSTATE_VIEW = "view";
  public static final String VALUE_FORMSTATE_EDIT = "edit";
  public static final String VALUE_FORMSTATE_CREATE = "create";
  public static final String CAPTION_FORMSTATE_VIEW = "查看";
  public static final String CAPTION_FORMSTATE_EDIT = "编辑";
  public static final String CAPTION_FORMSTATE_CREATE = "创建";
  public static final HashMap2 FORMSTATEMAP = new HashMap2().put2(VALUE_FORMSTATE_VIEW,
      CAPTION_FORMSTATE_VIEW).put2(VALUE_FORMSTATE_EDIT, CAPTION_FORMSTATE_EDIT).put2(
      VALUE_FORMSTATE_CREATE, CAPTION_FORMSTATE_CREATE);
  public static final String POSTFIX_FIELD_MISSING = "_missing";
  public static final String POSTFIX_FIELD_INVALID = "_invalid";
  public static final String POSTFIX_FIELD_INVALIDPERM = "_invalid_perm";
  public static final String POSTFIX_FIELD_ERROR = "_error";

  public static String getFormStateCaption(String formState) {
    return (String) FORMSTATEMAP.get(formState);
  }

  /**
   * @param codeName
   * @return String[0]=code, String[1]=name
   */
  public static String[] parseCodeName(String codeName) {
    String[] result = new String[] {
        "", "" };
    if (codeName != null) {
      int i = codeName.indexOf("[");
      if (i > 0) {
        result[0] = codeName.substring(0, i);
        result[1] = codeName.substring(i + 1, codeName.length() - 1);
      }
    }
    return result;
  }

  /**
   * 将金额转换成大写
   * 
   * @param Money
   * @return
   */
  public static String moneyToWord(BigDecimal Money) {
    StringBuffer sb = new StringBuffer();
    String[] Words = {
        "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
    String[] Units = {
        "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万" };
    BigDecimal iMoney, fMoney, Jiao, Fen, Zero = new BigDecimal(0), Ten = new BigDecimal(10);
    int i;
    int[] Digits = new int[13];

    Money = Money.setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.print(Money);
    iMoney = Money.setScale(0, BigDecimal.ROUND_DOWN);
    fMoney = Money.subtract(iMoney).multiply(new BigDecimal(100));
    Jiao = fMoney.divide(Ten, 0, BigDecimal.ROUND_DOWN);
    Fen = fMoney.subtract(Jiao.multiply(Ten));
    if (iMoney.compareTo(new BigDecimal(10000000000000.00)) >= 0)
      return "超出表示范围";
    i = 0;
    while (iMoney.compareTo(Zero) != 0) {
      Digits[i] = iMoney.subtract(iMoney.divide(Ten, 0, BigDecimal.ROUND_DOWN).multiply(Ten))
          .intValue();
      iMoney = iMoney.divide(Ten, 0, BigDecimal.ROUND_DOWN);
      ++i;
    }
    --i;
    int nz = 0;
    while (i >= 0) {
      if (Digits[i] != 0) {
        sb.append(Words[Digits[i]] + Units[i]);
        nz = i;
      } else {
        if (i % 4 != 0) {
          if (Digits[i - 1] != 0)
            sb.append(Words[Digits[i]]);
        } else {
          if (i == 0 || nz != 8)
            sb.append(Units[i]);
        }
      }
      --i;
    }
    if (Jiao.intValue() != 0)
      sb.append(Words[Jiao.intValue()] + "角");
    else if ((Fen.intValue() != 0) && (sb.length() > 0))
      sb.append("零");
    if (Fen.intValue() != 0)
      sb.append(Words[Fen.intValue()] + "分");
    if (sb.length() == 0)
      sb.append("零元零角零分");
    if (Jiao.intValue() == 0 && Fen.intValue() == 0)
      sb.append("整");

    return sb.toString();
  }

  // ////////////////////////////
  // About JavaScript

  /**
   * 将一个String类型值转换为JavaScript的常量。
   * 
   * @param value
   * @return
   */
  public static String toJSConst(String value) {
    return (value == null) ? "null" : "\"" + value + "\"";
  }

  /**
   * 将一个Integer类型值转换为JavaScript的常量。
   * 
   * @param value
   * @return
   */
  public static String toJSConst(Integer value) {
    return (value == null) ? "null" : value.toString();
  }

  /**
   * 将一个Boolean类型值转换为JavaScript的常量。
   * 
   * 
   * @param value
   * @return
   */
  public static String toJSConst(Boolean value) {
    if (value == null)
      return "null";
    else if (value.booleanValue())
      return "true";
    else
      return "false";
  }

  /**
   * 将一个BigDecimal类型值转换为JavaScript的常量。
   * 
   * @param value
   * @return
   */
  public static String toJSConst(BigDecimal value) {
    return (value == null) ? "null" : value.toString();
  }

  /**
   * 将一个Date类型值转换为JavaScript的常量。
   * 
   * @param value
   * @return
   */
  public static String toJSConst(Date value) {
    return (value == null) ? "null" : "new Date(" + value.getTime() + ")";
  }

  /**
   * 将一个对象数组转换为JavaScript的数组常量。
   * 
   * @param arr
   * @return
   */
  public static String toJSArrayConst(Object[] arr) throws Exception {
    String result = "";
    for (int i = 0; i < arr.length; i++) {
      if (i != 0)
        result = result + ", ";
      result = result + toJSObjectConst(arr[i]);
    }
    return "[" + result + "]";
  }

  /**
   * 将一个对象数组转换为JavaScript的数组常量。
   * 
   * @param arr
   * @param fields
   *          指定需要转换的字段数组。
   * @return
   * @throws Exception
   */
  public static String toJSArrayConst(Object[] arr, String[] fields) throws Exception {
    String result = "";
    for (int i = 0; i < arr.length; i++) {
      if (i != 0)
        result = result + ", ";
      result = result + toJSObjectConst(arr[i], fields);
    }
    return "[" + result + "]";
  }

  /**
   * 将一个List转换为JavaScript的数组常量。
   * 
   * @param list
   * @return
   */
  public static String toJSArrayConst(List list) throws Exception {
    String result = "";
    for (int i = 0; i < list.size(); i++) {
      if (i != 0)
        result = result + ", ";
      result = result + toJSObjectConst(list.get(i));
    }
    return "[" + result + "]";
  }

  /**
   * 将一个List转换为JavaScript的数组常量。
   * 
   * @param list
   * @param fields
   *          指定需要转换的字段数组。
   * @return
   * @throws Exception
   */
  public static String toJSArrayConst(List list, String[] fields) throws Exception {
    String result = "";
    for (int i = 0; i < list.size(); i++) {
      if (i != 0)
        result = result + ", ";
      result = result + toJSObjectConst(list.get(i), fields);
    }
    return "[" + result + "]";
  }

  /**
   * 将一个对象转换为JavaScript的对象常量。
   * 
   * @param obj
   * @return
   */
  public static String toJSObjectConst(Object obj) throws Exception {
    if (obj instanceof String)
      return toJSConst((String) obj);
    if (obj instanceof Integer)
      return toJSConst((Integer) obj);
    if (obj instanceof BigDecimal)
      return toJSConst((BigDecimal) obj);
    if (obj instanceof Boolean)
      return toJSConst((Boolean) obj);
    if (obj instanceof Date)
      return toJSConst((Date) obj);

    String result = "";
    Field[] fields = obj.getClass().getFields();
    for (int i = 0; i < fields.length; i++) {
      if (i != 0)
        result = result + ", ";
      result = result + fields[i].getName() + ": ";
      Object value = fields[i].get(null);
      if (value instanceof List)
        result = result + toJSArrayConst((List) value);
      else if (value instanceof Object[])
        result = result + toJSArrayConst((Object[]) value);
      else
        result = result + toJSObjectConst(value);
    }

    return "{" + result + "}";
  }

  /**
   * 将一个对象转换为JavaScript的对象常量。
   * 
   * @param obj
   * @param fields
   *          指定需要转换的字段数组。
   * @return
   * @throws Exception
   */
  public static String toJSObjectConst(Object obj, String[] fields) throws Exception {
    String result = "";
    for (int i = 0; i < fields.length; i++) {
      if (i != 0)
        result = result + ", ";
      Field field = obj.getClass().getField(fields[i]);
      result = result + field.getName();
      Object value = field.get(null);
      if (value instanceof List)
        result = result + toJSArrayConst((List) value);
      else if (value instanceof Object[])
        result = result + toJSArrayConst((Object[]) value);
      else
        result = result + toJSObjectConst(value);
    }
    return "{" + result + "}";
  }

  /**
   * 
   * @param link
   * @return
   */
  public static String toJSActionConst(String link) {
    return (link == null) ? "null" : toJSConst(getAction(link));
  }
}
